home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 November: Tool Chest / Dev.CD Nov 98 TC.toast / Sample Code / Devices / ADB Key Spy 1.0.1b3 / ADBKS Extension.c < prev    next >
Encoding:
Text File  |  1997-03-07  |  6.8 KB  |  298 lines  |  [TEXT/R*ch]

  1.     //
  2.     //    from 'ADB Key Spy' • Pete Gontier • gurgle@apple.com
  3.     //    Macintosh Developer Technical Support
  4.     //    © 1995,1996 Apple Computer, Inc.
  5.     //
  6.     //    Changes:
  7.     //
  8.     //        when        who        what
  9.     //        --------------------------------------------------------------
  10.     //        11/12/96    Quinn    modified to use TradDriverLoaderLib
  11.     //        01/11/96    PG        copied from another project,
  12.     //                            merged with various parts of old
  13.     //                            ADB Key Spy
  14.     //
  15.  
  16. #ifndef __DEVICES__
  17. #    include <Devices.h>
  18. #endif
  19.  
  20. #ifndef __RESOURCES__
  21. #    include <Resources.h>
  22. #endif
  23.  
  24. #ifndef __MEMORY__
  25. #    include <Memory.h>
  26. #endif
  27.  
  28. #ifndef __LOWMEM__
  29. #    include <LowMem.h>
  30. #endif
  31.  
  32. #ifndef __A4STUFF__
  33. #    include <A4Stuff.h>
  34. #endif
  35.  
  36. #include "ADBKS Common.h"
  37. #include "ADBKS csCodes.h"
  38.  
  39. #include "TradDriverLoaderLib.h"
  40.  
  41.     //
  42.     //    vKeyboardServiceRoutineAsm
  43.     //
  44.     //    This is a declaration for a function which is in fact
  45.     //    never called from C but only by ADB and consists of 68K
  46.     //    assembly. However, I pass the thing around enough that
  47.     //    it was convenient to define a type for it.
  48.     //
  49.  
  50. typedef asm void (vKeyboardServiceRoutineAsm) (void);
  51.  
  52.     //
  53.     //    dCtlFlags
  54.     //
  55.     //    These are the device control entry flags for the driver.
  56.     //    Compiler doesn't allow me to specify them with quite enough
  57.     //    flexibility (i.e. none), and I don't want to put a manual
  58.     //    resource edit into the build process, so I have code do it.
  59.     //
  60.  
  61. const short dCtlFlags = dRAMBasedMask | dCtlEnableMask | dStatEnableMask;
  62.  
  63. enum
  64. {
  65.     //
  66.     //    Some miscellaneous quantities needed for installing a driver
  67.     //    into the unit table which for whatever reason do not
  68.     //    appear in <Devices.h>.
  69.     //
  70.  
  71.     kMaxUTEntries    = 128,    // maximum size of unit table
  72.     kMinUnitNum        = 48    // lowest unit number we can use
  73. };
  74.  
  75. static pascal OSErr GetKMAP (tKeyboardInfo *kbInfo, char devType)
  76. {
  77.     //
  78.     //    GetKMAP
  79.     //
  80.     //    The 'KMAP' resources map raw key codes to virtual key codes.
  81.     //    To make it possible for the service routine to easily perform
  82.     //    this mapping, we toss a handle to the appropriate 'KMAP'
  83.     //    resource into each keyboard info record.
  84.     //
  85.     //    The resource is marked locked, so it's interrupt-safe.
  86.     //    The resource is marked system-heap, which is what we want
  87.     //    because we are an INIT and our heap will disappear soon.
  88.     //
  89.     //    One is not supposed to release resources which potentially come from
  90.     //    the System file because they might be shared. Thus, we get our resource
  91.     //    and keep it ("leak" it). If you have 'KMAP' resources in some other file
  92.     //    for some reason, then you might want to call HomeResFile here to help
  93.     //    you decide whether to release the resource.
  94.     //
  95.  
  96.     OSErr err = noErr;
  97.  
  98.     const ResType kmapResType = 'KMAP';
  99.  
  100.     tKeyMapResourceH kmapH = (tKeyMapResourceH) GetResource (kmapResType, devType);
  101.     err = ResError ( );
  102.     if (err == resNotFound || !kmapH)
  103.     {
  104.         kmapH = (tKeyMapResourceH) GetResource (kmapResType, 0);
  105.         err = ResError ( );
  106.         if (err == resNotFound)
  107.         {
  108.             err = noErr;
  109.             kmapH = nil; // just to be sure
  110.         }
  111.     }
  112.  
  113.     kbInfo->keyMapResH = kmapH;
  114.  
  115.     return err;
  116. }
  117.  
  118. static pascal OSErr AcquireKeyboards
  119.     (vKeyboardServiceRoutineAsm *serviceRoutine, tKeyboardInfoP *keyboardInfoList)
  120. {
  121.     //
  122.     //    Walks the ADB device list and patches the service routine
  123.     //    of each keyboard so that an extra (internal) key map is maintained.
  124.     //    A block of memory is allocated via NewPtr for each keyboard.
  125.     //    Blocks are strung together into a list and returned.
  126.     //
  127.  
  128.     OSErr err = noErr;
  129.  
  130.     ADBSetInfoBlock        siBlock;
  131.     ADBDataBlock        adbInfo;
  132.  
  133.     short adbCount = CountADBs ( );
  134.  
  135.     *keyboardInfoList = nil;
  136.  
  137.     while (adbCount)
  138.     {
  139.         ADBAddress adbAddress = GetIndADB (&adbInfo, adbCount);
  140.  
  141.         if (adbAddress < 0)
  142.         {
  143.             DebugStr ("\p adbAddress < 0 ?");
  144.             err = paramErr;
  145.             break;
  146.         }
  147.  
  148.         if (adbInfo.origADBAddr == 2) // 2 == keyboard
  149.         {
  150.             //
  151.             //    allocate a new record to track old service proc addresses
  152.             //
  153.  
  154.             tKeyboardInfo *newKeyboardInfo =
  155.                 (tKeyboardInfo *) NewPtrSysClear (sizeof (tKeyboardInfo));
  156.             err = MemError ( );
  157.             if (err) break;
  158.  
  159.             //
  160.             //    fill in the new record and get ready to insert it into our list
  161.             //
  162.  
  163.             err = GetKMAP (newKeyboardInfo, adbInfo.devType);
  164.             if (err)
  165.             {
  166.                 DisposePtr ((Ptr) newKeyboardInfo);
  167.                 break;
  168.             }
  169.  
  170.             newKeyboardInfo->dbDataAreaAddr        = adbInfo.dbDataAreaAddr;
  171.             newKeyboardInfo->dbServiceRtPtr        = adbInfo.dbServiceRtPtr;
  172.             newKeyboardInfo->next                = *keyboardInfoList;
  173.  
  174.             //
  175.             //    replace the device's service routine and data pointer
  176.             //
  177.     
  178.             siBlock.siService        = (ADBServiceRoutineUPP) serviceRoutine;
  179.             siBlock.siDataAreaAddr    = (Ptr) newKeyboardInfo;
  180.  
  181.             err = SetADBInfo (&siBlock, adbAddress);
  182.             if (err)
  183.             {
  184.                 DisposePtr ((Ptr) newKeyboardInfo);
  185.                 break;
  186.             }
  187.  
  188.             //
  189.             //    insert the new record into our list
  190.             //
  191.  
  192.             *keyboardInfoList = newKeyboardInfo;
  193.         }
  194.  
  195.         --adbCount;
  196.     }
  197.  
  198.     return err;
  199. }
  200.  
  201. static pascal OSErr GetServiceRoutine (vKeyboardServiceRoutineAsm **ksra)
  202. {
  203.     //
  204.     //    Loads and detaches the ADB service routine code resource.
  205.     //    Produces the ADB service routine address.
  206.     //    A copy of the resource stays loaded; call DisposeHandle to free it.
  207.     //
  208.  
  209.     OSErr err = noErr;
  210.  
  211.     //
  212.     //    Assume AKSR 128 is system heap, locked, pre-load.
  213.     //
  214.  
  215.     Handle serviceRoutineH = Get1Resource ('AKSR',128);
  216.  
  217.     *ksra = nil;
  218.  
  219.     if (!(err = ResError ( )))
  220.     {
  221.         DetachResource (serviceRoutineH);
  222.         if (!(err = ResError ( )))
  223.             *ksra = (vKeyboardServiceRoutineAsm *) *serviceRoutineH;
  224.         else
  225.             ReleaseResource (serviceRoutineH);
  226.     }
  227.  
  228.     return err;
  229. }
  230.  
  231. static pascal OSErr AcquireKeyboardsAndLinkToDriver (ConstStr255Param myDriverName)
  232. {
  233.     //
  234.     //    Gets the address of the service routine.
  235.     //    Calls AquireKeyboards to patch all keyboard ADB service routines
  236.     //    and obtain a list of patched keyboard ADB info records.
  237.     //    Tells driver about this list.
  238.     //
  239.  
  240.     short drvrRefNum;
  241.  
  242.     OSErr err = OpenDriver (myDriverName, &drvrRefNum);
  243.  
  244.     if (!err)
  245.     {
  246.         OSErr err2 = noErr;
  247.         vKeyboardServiceRoutineAsm *ksra = nil;
  248.         if (!(err = GetServiceRoutine (&ksra)))
  249.         {
  250.             tKeyboardInfo *keyboardInfoList = nil;
  251.             err = AcquireKeyboards (ksra, &keyboardInfoList);
  252.  
  253.             //
  254.             //    Even if there was an error, there might be a partial list,
  255.             //    so we attempt to install it.
  256.             //
  257.  
  258.             if (keyboardInfoList)
  259.             {
  260.                 err2 = Control (drvrRefNum,kControlCode_SetKeyboardInfoList,&keyboardInfoList);
  261.                 if (!err) err = err2;
  262.             }
  263.         }
  264.     
  265.         //
  266.         //    Close the driver no matter what once it's been opened.
  267.         //    However, don't report errors on close unless nothing else
  268.         //    has gone wrong first.
  269.         //
  270.  
  271.         err2 = CloseDriver (drvrRefNum);
  272.         if (!err) err = err2;
  273.     }
  274.  
  275.     return err;
  276. }
  277.  
  278. void main (void)
  279. {
  280.     long oldA4 = SetCurrentA4 ( );
  281.     unsigned char *myDriverName = "\p.adb_key_spy";
  282.  
  283.     // Quinn 11/12/96
  284.     DriverRefNum drvrRefNum;
  285.     OSErr err;
  286.     err = TradInstallDriverFromResource(0, myDriverName,
  287.         48,
  288.         TradHighestUnitNumber() + 1,
  289.         &drvrRefNum);
  290.     if (err == noErr || err == dupFNErr) {
  291.         err = TradOpenInstalledDriver(drvrRefNum, fsRdWrPerm);
  292.     }
  293.     
  294.     if (!err) err = AcquireKeyboardsAndLinkToDriver (myDriverName);
  295.     if (err) SysBeep (10);
  296.     SetA4 (oldA4);
  297. }
  298.